/**
* Base code for file repositories.
*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
* @file
* @ingroup FileRepo
*/
var $oldFileFactory = false;
var $fileFactoryKey = false, $oldFileFactoryKey = false;
- function __construct( array $info = null ) {
+ /**
+ * @param $info array|null
+ * @throws MWException
+ */
+ public function __construct( array $info = null ) {
// Verify required settings presence
if(
$info === null
: array();
// Give defaults for the basic zones...
foreach ( array( 'public', 'thumb', 'temp', 'deleted' ) as $zone ) {
- if ( !isset( $this->zones[$zone] ) ) {
- $this->zones[$zone] = array(
- 'container' => "{$this->name}-{$zone}",
- 'directory' => '' // container root
- );
+ if ( !isset( $this->zones[$zone]['container'] ) ) {
+ $this->zones[$zone]['container'] = "{$this->name}-{$zone}";
+ }
+ if ( !isset( $this->zones[$zone]['directory'] ) ) {
+ $this->zones[$zone]['directory'] = '';
}
}
}
* Check if a single zone or list of zones is defined for usage
*
* @param $doZones Array Only do a particular zones
+ * @throws MWException
* @return Status
*/
protected function initZones( $doZones = array() ) {
* The suffix, if supplied, is considered to be unencoded, and will be
* URL-encoded before being returned.
*
- * @param $suffix string
+ * @param $suffix string|bool
* @return string
*/
public function getVirtualUrl( $suffix = false ) {
* @return String or false
*/
public function getZoneUrl( $zone ) {
+ if ( isset( $this->zones[$zone]['url'] )
+ && in_array( $zone, array( 'public', 'temp', 'thumb' ) ) )
+ {
+ return $this->zones[$zone]['url']; // custom URL
+ }
switch ( $zone ) {
case 'public':
return $this->url;
* Use this function wisely.
*
* @param $url string
+ * @throws MWException
* @return string
*/
public function resolveVirtualUrl( $url ) {
* SHA-1 content hash.
*
* STUB
+ * @param $hash
* @return array
*/
public function findBySha1( $hash ) {
/**
* Get the public root URL of the repository
*
+ * @deprecated since 1.20
* @return string
*/
public function getRootUrl() {
- return $this->url;
+ return $this->getZoneUrl( 'public' );
}
/**
* self::OVERWRITE_SAME Overwrite the file if the destination exists and has the
* same contents as the source
* self::SKIP_LOCKING Skip any file locking when doing the store
+ * @throws MWException
* @return FileRepoStatus
*/
public function storeBatch( array $triplets, $flags = 0 ) {
}
// Resolve source to a storage path if virtual
- if ( self::isVirtualUrl( $srcPath ) ) {
- $srcPath = $this->resolveVirtualUrl( $srcPath );
- }
+ $srcPath = $this->resolveToStoragePath( $srcPath );
// Get the appropriate file operation
if ( FileBackend::isStoragePath( $srcPath ) ) {
* Each file can be a (zone, rel) pair, virtual url, storage path.
* It will try to delete each file, but ignores any errors that may occur.
*
- * @param $pairs array List of files to delete
+ * @param $files array List of files to delete
* @param $flags Integer: bitwise combination of the following flags:
* self::SKIP_LOCKING Skip any file locking when doing the deletions
* @return FileRepoStatus
$path = $this->getZonePath( $zone ) . "/$rel";
} else {
// Resolve source to a storage path if virtual
- if ( self::isVirtualUrl( $path ) ) {
- $path = $this->resolveVirtualUrl( $path );
- }
+ $path = $this->resolveToStoragePath( $path );
}
$operations[] = array( 'op' => 'delete', 'src' => $path );
}
return $status;
}
+ /**
+ * Import a file from the local file system into the repo.
+ * This does no locking nor journaling and overrides existing files.
+ * This function can be used to write to otherwise read-only foreign repos.
+ * This is intended for copying generated thumbnails into the repo.
+ *
+ * @param $src string File system path
+ * @param $dst string Virtual URL or storage path
+ * @return FileRepoStatus
+ */
+ final public function quickImport( $src, $dst ) {
+ return $this->quickImportBatch( array( array( $src, $dst ) ) );
+ }
+
+ /**
+ * Purge a file from the repo. This does no locking nor journaling.
+ * This function can be used to write to otherwise read-only foreign repos.
+ * This is intended for purging thumbnails.
+ *
+ * @param $path string Virtual URL or storage path
+ * @return FileRepoStatus
+ */
+ final public function quickPurge( $path ) {
+ return $this->quickPurgeBatch( array( $path ) );
+ }
+
+ /**
+ * Deletes a directory if empty.
+ * This function can be used to write to otherwise read-only foreign repos.
+ *
+ * @param $dir string Virtual URL (or storage path) of directory to clean
+ * @return Status
+ */
+ public function quickCleanDir( $dir ) {
+ $status = $this->newGood();
+ $status->merge( $this->backend->clean(
+ array( 'dir' => $this->resolveToStoragePath( $dir ) ) ) );
+
+ return $status;
+ }
+
+ /**
+ * Import a batch of files from the local file system into the repo.
+ * This does no locking nor journaling and overrides existing files.
+ * This function can be used to write to otherwise read-only foreign repos.
+ * This is intended for copying generated thumbnails into the repo.
+ *
+ * @param $pairs Array List of tuples (file system path, virtual URL or storage path)
+ * @return FileRepoStatus
+ */
+ public function quickImportBatch( array $pairs ) {
+ $status = $this->newGood();
+ $operations = array();
+ foreach ( $pairs as $pair ) {
+ list ( $src, $dst ) = $pair;
+ $operations[] = array(
+ 'op' => 'store',
+ 'src' => $src,
+ 'dst' => $this->resolveToStoragePath( $dst )
+ );
+ $this->backend->prepare( array( 'dir' => dirname( $dst ) ) );
+ }
+ $status->merge( $this->backend->doQuickOperations( $operations ) );
+
+ return $status;
+ }
+
+ /**
+ * Purge a batch of files from the repo.
+ * This function can be used to write to otherwise read-only foreign repos.
+ * This does no locking nor journaling and is intended for purging thumbnails.
+ *
+ * @param $paths Array List of virtual URLs or storage paths
+ * @return FileRepoStatus
+ */
+ public function quickPurgeBatch( array $paths ) {
+ $status = $this->newGood();
+ $operations = array();
+ foreach ( $paths as $path ) {
+ $operations[] = array(
+ 'op' => 'delete',
+ 'src' => $this->resolveToStoragePath( $path ),
+ 'ignoreMissingSource' => true
+ );
+ }
+ $status->merge( $this->backend->doQuickOperations( $operations ) );
+
+ return $status;
+ }
+
/**
* Pick a random name in the temp zone and store a file to it.
* Returns a FileRepoStatus object with the file Virtual URL in the value,
* @param $triplets Array: (source, dest, archive) triplets as per publish()
* @param $flags Integer: bitfield, may be FileRepo::DELETE_SOURCE to indicate
* that the source files should be deleted if possible
+ * @throws MWException
* @return FileRepoStatus
*/
public function publishBatch( array $triplets, $flags = 0 ) {
foreach ( $triplets as $i => $triplet ) {
list( $srcPath, $dstRel, $archiveRel ) = $triplet;
// Resolve source to a storage path if virtual
- if ( substr( $srcPath, 0, 9 ) == 'mwrepo://' ) {
- $srcPath = $this->resolveVirtualUrl( $srcPath );
- }
+ $srcPath = $this->resolveToStoragePath( $srcPath );
if ( !$this->validateFilename( $dstRel ) ) {
throw new MWException( 'Validation error in $dstRel' );
}
return $status;
}
+ /**
+ * Deletes a directory if empty.
+ *
+ * @param $dir string Virtual URL (or storage path) of directory to clean
+ * @return Status
+ */
+ public function cleanDir( $dir ) {
+ $this->assertWritableRepo(); // fail out if read-only
+
+ $status = $this->newGood();
+ $status->merge( $this->backend->clean(
+ array( 'dir' => $this->resolveToStoragePath( $dir ) ) ) );
+
+ return $status;
+ }
+
/**
* Checks existence of a a file
*
public function fileExistsBatch( array $files ) {
$result = array();
foreach ( $files as $key => $file ) {
- if ( self::isVirtualUrl( $file ) ) {
- $file = $this->resolveVirtualUrl( $file );
- }
+ $file = $this->resolveToStoragePath( $file );
$result[$key] = $this->backend->fileExists( array( 'src' => $file ) );
}
return $result;
* is a two-element array containing the source file path relative to the
* public root in the first element, and the archive file path relative
* to the deleted zone root in the second element.
+ * @throws MWException
* @return FileRepoStatus
*/
public function deleteBatch( array $sourceDestPairs ) {
* Get a relative path for a deletion archive key,
* e.g. s/z/a/ for sza251lrxrc1jad41h5mgilp8nysje52.jpg
*
+ * @param $key string
* @return string
*/
public function getDeletedHashPath( $key ) {
/**
* Create a new good result
*
+ * @param $value null|string
* @return FileRepoStatus
*/
public function newGood( $value = null ) {